#include "precompiled.h"

namespace IcyCrystal {
	Parser::Parser(Lexer& lexer) : lexer(lexer){
		currentLevel = 0;
		currentConstCount = 0;

		// Set up the global namespace
		globalNamespace.up = NULL;
		globalNamespace.scope = SCOPE_GLOBAL;
	}
	
	void Parser::createSystemTypes(){
		intType = new Type;
		intType->primitiveType = PRIM_TYPE_INT;
		intType->size = 4;

		floatType = new Type;
		floatType->primitiveType = PRIM_TYPE_FLOAT;
		floatType->size = 4;

		charType = new Type;
		charType->primitiveType = PRIM_TYPE_CHAR;
		charType->size = 1;

		globalNamespace.types.push_back(intType);
		globalNamespace.types.push_back(floatType);
	}
	
	Symbol* Parser::addConstantToTable(Namespace* currentNamespace, Type* type){
		Symbol* symb = new Symbol();
		stringstream sname;
		sname << "CONST_" << currentConstCount;
		symb->symbolName = sname.str();

		symb->level = currentLevel;
		symb->type = *type;
		symb->scope = currentNamespace->scope;
		
		currentNamespace->ConstantMap[symb->symbolName] = symb;
		return symb;
	}

	Symbol* Parser::addPrimitiveToTable(Namespace* currentNamespace, Type* type, Token* keyword ){
		// Create the new symbol.
		Symbol* symb = new Symbol();
		symb->symbolName = *keyword->value.stringValue;
		symb->level = currentLevel;

		symb->type = *type;
		//delete type;
		
		symb->scope = currentNamespace->scope;

		if( symb->scope == SCOPE_CONSTANT )
			currentNamespace->ConstantMap[symb->symbolName] = symb;
		else
			currentNamespace->SymbolMap[symb->symbolName] = symb;

		return symb;
	}

	Symbol* Parser::addStringToTable(Namespace* currentNamespace, Token& token){
		// Each string is its own type - with it's size ( so the compiler can know )

		// Create the STRING's symbol
		Symbol* symb = new Symbol();
		stringstream symName;
		symName << "string_" << currentConstCount;
		symb->symbolName = symName.str();
		symb->level = 0;
		symb->scope = SCOPE_CONSTANT;

		// Create the type.
		symb->type.primitiveType = PRIM_TYPE_STRING;  // We never use the label directly
		symb->type.size = token.value.stringValue->length() + 1;
		symb->consts.stringConst = new string(*token.value.stringValue);

		globalNamespace.ConstantMap[symb->symbolName] = symb;
		
		currentConstCount++;

		return symb;
	}

	Type* Parser::getRootType(Type* type){
		while( type->primitiveType == PRIM_TYPE_POINTER || type->primitiveType == PRIM_TYPE_ARRAY ){
			type = type->extra.pointTo;
		}
		return type;
	}

	SyntaxTree* Parser::createStatAssign(Namespace* currentNamespace, SyntaxTree* symbolTree, SyntaxTree* rvalue) {
		

		/**
		* array = {1,2,3}
		* array = anotherArray
		* array[] = {1,2,3}
		*/
		if( rvalue->nodeFlags == NODE_IS_ARRAY_INITIATOR && symbolTree->expressionReturnType->arraySize == ARRAY_ELEM_WAIT ){
			symbolTree->expressionReturnType->arraySize = ARRAY_ELEM_CONST;
			symbolTree->expressionReturnType->arrayAccess.constNumElems = rvalue->extra.arrayInitArguments->size();

			// Compute the array size.

			if( !arrayIsVLA(symbolTree->expressionReturnType ) ){
				// Figure out the size.
				computeArraySize(currentNamespace, symbolTree->expressionReturnType);
			}
			else {
				throw ParserException("Do not support VLAs yet");
			}

			
		}

		if( rvalue->nodeFlags == NODE_IS_ARRAY_INITIATOR ){
			// All elements take the type of their corresponding level type, with promotions if necessary
			rvalue->expressionReturnType = symbolTree->expressionReturnType;
			Type* lType = symbolTree->expressionReturnType;
			Type* rType = rvalue->expressionReturnType;
			

			validateArrayInitializer(currentNamespace,lType, rvalue);
			lType = NULL;
		}

		/** Two possibilities:
		* Global:
		*   ONLY declarations are allowed in global.
		* Local
		*/
		
		SyntaxTree* ret = new SyntaxTree();

		if( currentNamespace->scope == SCOPE_GLOBAL ){
			/** Must link rvalue with the symbol*/
			// TODO: Useless tree. Remove.
			ret->nodeType = NODE_INITIALIZE;
			ret->left = symbolTree;
			ret->right = rvalue;
			symbolTree->inner.sym->consts.exprConst = rvalue;
		}
		else {
			ret->nodeType = NODE_ASSIGN;
			ret->left = symbolTree;
			ret->right = rvalue;
			ret->expressionReturnType = symbolTree->expressionReturnType;

			// Make sure both types are compatible.
			if( ret->left->inner.sym->type.primitiveType != rvalue->expressionReturnType->primitiveType ){
				promoteAndConvertOp(ret);
				// TODO: Free memory on error.
			}
		}

		return ret;
	}

	Type* Parser::getTypeSpecifier(Token* firstToken, Type* rec){
		Token* c = firstToken;
		Type* ret = new Type;
		if( c->tokenType == TOKEN_IDENT_INT ){
			*ret = *intType;
		}
		else if( c->tokenType == TOKEN_IDENT_FLOAT ){
			*ret = *floatType;
		}
		else if( c->tokenType == TOKEN_IDENT_CHAR ){
			*ret = *charType;
		}
		else if( rec == NULL )
			return NULL; // Not a type specifier.

		// Check for pointers.
		if( rec == NULL )
			rec = ret; // Points to self if only star
		Token* k = lexer.getReadAheadToken();
		if( k->tokenType == TOKEN_MULT ){
			// We have a pointer!
			Type* newType = new Type;
			newType->primitiveType = PRIM_TYPE_POINTER;
			newType->extra.pointTo = rec;

			c = lexer.getNextToken();

			// Recursive call
			newType = getTypeSpecifier(c, newType);
			return newType;
		}
		else {
			// End of recursive call, OR not a pointer.
			return rec;
		}
		
		
	}

	SyntaxTree* Parser::createVariableDeclaration(Token* startingToken, Namespace* currentNamespace){
		//Symbol* innerSymbol;
		Token* c = startingToken;
		Token* k = NULL;
		SyntaxTree* variableTree;

		Type* ident = getTypeSpecifier(c, NULL );
		if( ident != NULL ){
			// We have a type specifier.
			c = lexer.getNextToken();

			// Get a variable.
			variableTree = getVariable(c,currentNamespace, ident);
			if( variableTree == NULL)
				return NULL; // This is a function

			/**
			* In the case of global arrays that are initialized using
			* array = {0,1,..,n}
			* The initialization is part of the creation (hardcoded values)
			* -------
			* However, in the case of local arrays, for simplicity's sake,
			* I will implement the initialization as a shortcut to individual assignment.
			*/
			if(variableTree->expressionReturnType && variableTree->expressionReturnType->primitiveType == PRIM_TYPE_ARRAY ){
				k = lexer.getReadAheadToken();
				if( variableTree->expressionReturnType->arraySize ==  ARRAY_ELEM_WAIT && !TIS_EQUALS(k) ){
					// TODO: Free the stuff at the top
					throw ParserException("TOKEN_EQUALS", variableTree->expressionReturnType->primitiveTypeToString(), lexer.fileReader.getCurrentLine());
				}

				// If its not WAIT, we can compute size now.
				if( variableTree->expressionReturnType->arraySize == ARRAY_ELEM_CONST && !arrayIsVLA(variableTree->expressionReturnType)){
					computeArraySize(currentNamespace, variableTree->expressionReturnType);
				}

				// Since this is an array, our variable type is the real type.
				//variableTree->right->expressionReturnType = variableTree->expressionReturnType->extra.pointTo;
			}
			

			// Update types.
			if( (!variableTree->expressionReturnType) && variableTree->nodeType == NODE_SYMBOL ){
				variableTree->inner.sym->type = *ident;
				variableTree->expressionReturnType = &variableTree->inner.sym->type;
				// No more use for type
				delete ident;
			}
			if( (!variableTree->expressionReturnType) && variableTree->nodeType == NODE_TOKEN ){
				variableTree->expressionReturnType = ident;
			}
		}
		else{
			// No type specifiers.
			return NULL;
		}
		
		// Create the try to return
		return variableTree;

	}


	SyntaxTree* Parser::getVariable(Token* startingToken, Namespace* currentNamespace, Type* preType){
		/**
		* startingToken: Keyword token - not null only if this is the first call.
		* preType: The type called before. Either through recursion or a variable initialization.
		* startingToken is Keyword && preType : iff This is a first of variable declaration
		* startingToken is Keyword && !preType : iff This is a first of a normal variable return
		*/
		
		Token* c = startingToken;
		Token* keywordToken;
		Symbol* initSym;
		if( !TIS_KEYWORD(c) ){
			throw ParserException("KEYWORD", c->tokenTypeToString(), lexer.fileReader.getCurrentLine());
		}

		if( TIS_LPARA(lexer.getReadAheadToken()) ){
			// This is a function. Not a variable.
			SyntaxTree* retTree = new SyntaxTree;
			retTree->nodeType = NODE_TOKEN;
			retTree->inner.nodeToken.tokenType = TOKEN_KEYWORD;
			retTree->inner.nodeToken.value.stringValue = new string(*c->value.stringValue);
			return retTree;
		}
		
		// Get the parent symbol 
		if( TIS_KEYWORD(c) && preType ){
			// Create the symbol.
			initSym = addPrimitiveToTable(currentNamespace, preType, c );
		}
		else if( TIS_KEYWORD(c) && !preType ){
			// Keyword must already exist.

			if( (initSym = currentNamespace->findSymbol(*c->value.stringValue)) == NULL ){
				throw SymbolException(*c->value.stringValue, "not found", lexer.fileReader.getCurrentLine());
			}

		}
		else{
			throw new exception();	
		}

		// Build the tree.
		SyntaxTree* retTree = new SyntaxTree;
		retTree->nodeType = NODE_SYMBOL;
		retTree->expressionReturnType = &initSym->type;
		retTree->inner.sym = initSym;

		// Check for arrays.
		Token* k = lexer.getReadAheadToken();
		if( TIS_LSQUARE(k) && preType){
			// This is an array DECLARATION.
			Type* type = getArrayInitType(currentNamespace, preType, true);
 			// Replace the symbol's type.
			initSym->type = *type;
			delete type;
		}
		else if( TIS_LSQUARE(k) ){
			// Replace us!
			SyntaxTree* arrayAccess = getArrayAccess(currentNamespace, &initSym->type, initSym);
			delete retTree;
			arrayAccess->nodeType = NODE_SYMBOL;
			arrayAccess->nodeFlags = NODE_IS_ARRAY_ACCESS;
			retTree = arrayAccess;
		}

		return retTree;
	}

	SyntaxTree* Parser::getNextStatement(Namespace* currentNamespace){
		SyntaxTree* ret = new SyntaxTree();
		Token* c = lexer.getNextToken();
		Token* k = NULL;

		/**
		* Possible scenarios:
		* ident keyword;
		* ident keyword = expression;
		* keyword = expression;
		*/

		SyntaxTree* isDeclaration = createVariableDeclaration(c, currentNamespace);
		if( isDeclaration && isDeclaration->nodeType == NODE_TOKEN ){
			bool isDecl;
			// Function
			c = lexer.getNextToken();
			// c is LPARA
			// Build the argument list
			SymbolList* list = getArgumentDeclList(currentNamespace);
			bool funcExists = functionIsDefined(*isDeclaration->inner.nodeToken.value.stringValue);

			c = lexer.getNextToken();

			if( TIS_SEMICOLON(c) ){
				isDecl = true;
			}
			else if( TIS_LCURLY(c) ){
				isDecl = false;
			}

			/** Verify that the function can be defined */
			if( isDecl && funcExists ){
				// TODO: Free stuff
				throw SymbolException(string("Function " + *isDeclaration->inner.nodeToken.value.stringValue), "is already defined.",currentLine());
			}
			else if( (!isDecl) && funcExists ){
				// Delete the old symbol
				Symbol* old = globalNamespace.FunctionMap[*isDeclaration->inner.nodeToken.value.stringValue];
				globalNamespace.FunctionMap.erase(*isDeclaration->inner.nodeToken.value.stringValue);
				delete old;
			}
			
			verifyArgumentDeclList(list, isDecl);
			Symbol* funcSymbol = createFunctionDeclaration(isDeclaration->inner.nodeToken.value.stringValue,isDeclaration->expressionReturnType,list);

			/** Declaration only, or full body? */
			if( !isDecl ){
				// Get the body
				SyntaxTreeList* body = generateBlock(funcSymbol->consts.function.functionNamespace);
				funcSymbol->consts.function.functionBody = body;
				return NULL; // Useless node.
			}
			else {
				// Just a declaration
				throw new exception();
			}
			int i = 7;
		}
		else if( isDeclaration && isDeclaration->nodeType == NODE_SYMBOL){
			/**
			* ident keyword;
			* ident keyword = expression;
			*/
			k = lexer.getReadAheadToken();
			if( k->tokenType == TOKEN_SEMICOLON || k->tokenType == TOKEN_EQUALS){
				// Add to table anyway.
				/**
				* ident keyword;
				*/
				// Get rid of semicolon.
				if( k->tokenType == TOKEN_SEMICOLON )
					lexer.getNextToken();

				ret->nodeType = NODE_INITIALIZE;
				ret->left = isDeclaration;
			}
			else {
				throw ParserException("TOKEN_SEMICOLON or TOKEN_EQUALS", k->tokenTypeToString(), currentLine());
			}

			if( k->tokenType == TOKEN_EQUALS ){					
				/** ident keyword = expression; */
				// Find the expression
				lexer.getNextToken();
				SyntaxTree* expression = getNextExpression(currentNamespace);

				// Force add the current initialization.
				syntaxList.push_back(ret);
					
				ret = createStatAssign(currentNamespace, isDeclaration, expression );

				//delete k;
				k = lexer.getReadAheadToken();

				if( k->tokenType == TOKEN_SEMICOLON ){
					lexer.getNextToken();
				}
				else {
					throw ParserException("TOKEN_SEMICOLON", c->tokenTypeToString(), currentLine());
				}
			}
		}
		else if( c->tokenType == TOKEN_KEYWORD ){
			/**
			* keyword = expression;
			*/

			// Maybe is a variable
			SyntaxTree* var = getVariable(c, currentNamespace, NULL );

			k = lexer.getReadAheadToken();
			if(var!= NULL &&  k->tokenType == TOKEN_EQUALS ){
				/**
				* keyword = expression.
				*/
				lexer.getNextToken();
				// Get the expression.
				SyntaxTree* expression = getNextExpression(currentNamespace);
				//delete ret;
				ret = createStatAssign(currentNamespace, var,expression );

				// Check the semicolon.
				
				k = lexer.getReadAheadToken();
				if( k->tokenType == TOKEN_SEMICOLON ){
					lexer.getNextToken();
				}
				else {
					throw ParserException("TOKEN_SEMICOLON", k->tokenTypeToString(), currentLine());
				}
			}
		}
		else if( c->tokenType == TOKEN_RETURN ){
			// Return statement.
			ret->nodeType = NODE_RETURN;
			// Get the expression to return;
			k= lexer.getReadAheadToken();
			if( ! TIS_SEMICOLON(k) ){
				SyntaxTree* retExpr = getNextExpression(currentNamespace);
				ret->left = retExpr;
			}
			
			c = lexer.getNextToken();
			if( ! TIS_SEMICOLON(c)){
				throw ParserException("TOKEN_SEMICOLON", c->tokenTypeToString(), currentLine());
			}
		}
		else if( TIS_RCURLY(c) ){
			ret->nodeType = NODE_BLOCK_END;
		}
		else if( c->tokenType == TOKEN_EOF ) {
			ret->nodeType = NODE_EOF;
		}
		
		else {
			throw ParserException("STATEMENT",c->tokenTypeToString(), currentLine());
		}

		return ret;
	}

	SyntaxTree* Parser::getNextExpression(Namespace* currentNamespace){
		SyntaxTree* newTree = new SyntaxTree();
		Token* c = lexer.getNextToken();


		/** Possible scenarios:
		* number
		* symbol
		* expression + - * / expression
		*/
		if( c->tokenType == TOKEN_KEYWORD ){
			// This is maybe a variable.
			SyntaxTree* var = getVariable(c,currentNamespace, NULL);
			if( var!= NULL ){
				delete newTree;
				newTree = var;
			}
			else
				throw ParserException("We only support variables!");
		}
		else if( TIS_LCURLY(c) ){
			// Expression in the form of {o0,o1,..,on}
			// Where o is a datatype.
			SyntaxTreeList* list = getArgumentList(currentNamespace,TOKEN_RCURLY);

			// Create a constant symbol that describes that array
			Type arrayType ;
			arrayType.primitiveType = PRIM_TYPE_ARRAY;
			arrayType.arraySize = ARRAY_ELEM_CONST;
			arrayType.size = list->size();

			//Symbol* tempSymb = addConstantToTable(currentNamespace, &arrayType);
			Symbol* tempSymb = new Symbol;

			// Return a symbol
			newTree->nodeType = NODE_SYMBOL;
			newTree->expressionReturnType = &tempSymb->type;
			newTree->inner.sym = tempSymb;
			newTree->nodeFlags = NODE_IS_ARRAY_INITIATOR;
			newTree->extra.arrayInitArguments = list;
		}
		else if( c->tokenType == TOKEN_INT ){
			newTree->nodeType = NODE_TOKEN;
			newTree->inner.nodeToken = *c;

			newTree->inner.nodeToken.innerType = intType;
			newTree->expressionReturnType = intType;
		}
		else if( c->tokenType == TOKEN_FLOAT ){
			newTree->nodeType = NODE_TOKEN;
			newTree->inner.nodeToken = *c;

			newTree->inner.nodeToken.innerType = floatType;
			newTree->expressionReturnType = floatType;
		}
		else if( c->tokenType == TOKEN_STRING ){
			// Get the first char
			Symbol* str = addStringToTable(currentNamespace, *c);
			
			// Create the actual symbol.
			
			newTree->nodeType = NODE_SYMBOL;
			newTree->inner.sym = str;

			// Even though it's not really a pointer - logically - string's type is const char*
			newTree->expressionReturnType = &str->type;
		}
		else {
			throw ParserException("EXPRESSION",c->tokenTypeToString(),currentLine() );
		}	

		// Check for operators on expressions
		Token* d = lexer.getReadAheadToken();
		if( d->tokenType == TOKEN_EQUALS ){
			// We have an assignment expression.
			Token* keyword = new Token( *c) ;
			c = lexer.getNextToken();

			SyntaxTree* rExp = getNextExpression(currentNamespace);

			SyntaxTree* assignStatement = createStatAssign(currentNamespace, newTree, rExp);
			delete keyword;

			// Move 
			delete newTree;
			newTree = assignStatement;

			// It is not an assign anymore
		}
		else if( d->tokenType == TOKEN_PLUS || d->tokenType == TOKEN_MINUS ||
			d->tokenType == TOKEN_MULT || d->tokenType == TOKEN_DIV){
			// We are acting on two expressions. Make sure the types agree.
			//delete c;
			SyntaxTree* myOp = new SyntaxTree();
			c = lexer.getNextToken();
			myOp->inner.nodeToken = *c;

			// Get the right hand side
			SyntaxTree* rExp = getNextExpression(currentNamespace);

			
			myOp->nodeType = NODE_EXPRESSION;
			myOp->expressionReturnType = newTree->expressionReturnType;

			myOp->left = newTree;

			// Only check for associativity if the right side is an expression
			if( rExp->nodeType == NODE_EXPRESSION  ){
				int myLevel = getOpLevel( myOp->inner.nodeToken.tokenType );
				int otherLevel = getOpLevel( rExp->inner.nodeToken.tokenType );
				if( myLevel >= otherLevel ){
					// Fix for associativity.
					SyntaxTree* otherLeft = rExp->left;
					myOp->right = otherLeft;
					rExp->left = myOp;
					// Replace
					newTree = rExp;
				}
				else {
					myOp->right = rExp;
					newTree = myOp;
				}
			}
			else if( rExp->nodeType == NODE_TOKEN || rExp->nodeType == NODE_SYMBOL){
				// Always no association
				myOp->right = rExp;
				newTree = myOp;
			}
			else {
				throw ParserException("EXPRESSION", "INVALID", lexer.fileReader.getCurrentLine());
			}


			// Convert if needed.
			if( newTree->left->expressionReturnType->primitiveType != newTree->right->expressionReturnType->primitiveType){
				promoteAndConvertOp(newTree);
				// TODO: Delete data with exceptions.
			}
		}

		

		//delete c;

		return newTree;
		
	}

	// PRE: lType != rType
	void Parser::promoteAndConvertOp(SyntaxTree* rootNode){
		// Find the type of both nodes.
		SyntaxTree *lNode = rootNode->left, *rNode = rootNode->right;
		Type* lType = lNode->expressionReturnType;
		Type* rType = rNode->expressionReturnType;

		// Are they both numerals?
		if( isTypeNumeral(lType) && isTypeNumeral(rType)){
			// Promotion amongst numerals:
			// Int can get promoted to float

			if( lType->primitiveType == PRIM_TYPE_FLOAT && rType->primitiveType == PRIM_TYPE_INT ){
				// Convert rType
				rootNode->right = promoteIntToFloat(rNode);
			}
			else if( lType->primitiveType == PRIM_TYPE_INT && rType->primitiveType == PRIM_TYPE_FLOAT
				&& rootNode->nodeType != NODE_ASSIGN){
				// Convert lType
				rootNode->left = promoteIntToFloat(lNode);
				
			}
			else {
				throw ConversionException(lType->primitiveTypeToString(), rType->primitiveTypeToString(), lexer.fileReader.getCurrentLine());
			}
		}
		//else if( lType->primitiveType == PRIM_TYPE_POINTER && lType->primitiveType != PRIM_TYPE_POINTER ){
			
		//}
		else if( lType->primitiveType == PRIM_TYPE_STRING || rType->primitiveType == PRIM_TYPE_STRING ){
			if( lType->primitiveType == PRIM_TYPE_STRING ){
				rootNode->left = promoteStringToPointer(lNode);
			}
			if( rType->primitiveType == PRIM_TYPE_STRING ){
				rootNode->right = promoteStringToPointer(rootNode->right);
			}
		}
		else {
			throw ConversionException(lType->primitiveTypeToString(), rType->primitiveTypeToString(), lexer.fileReader.getCurrentLine());
		}

		// No conversion needed.
	}

	SyntaxTree* Parser::promoteIntToFloat(SyntaxTree* node){
		SyntaxTree* convTree = new SyntaxTree;
		convTree->nodeType = NODE_EXPRESSION;
		convTree->inner.nodeToken.tokenType = TOKEN_CONV_INT_TO_FLOAT;
		convTree->expressionReturnType = floatType;
		convTree->left = node;

		return convTree;
	}
	
	SyntaxTree* Parser::promoteStringToPointer(SyntaxTree* node){
		SyntaxTree* convTree = new SyntaxTree;
		convTree->nodeType = NODE_EXPRESSION;
		convTree->inner.nodeToken.tokenType = TOKEN_CONV_LITERAL;
		Type* tempType = new Type;
		tempType->primitiveType = PRIM_TYPE_POINTER;
		tempType->extra.pointTo = charType;
		convTree->expressionReturnType = tempType;

		convTree->left = node;
		return convTree;
	}
	
	bool Parser::isTypeNumeral(Type* type){
		switch( type->primitiveType ){
		case PRIM_TYPE_INT:
		case PRIM_TYPE_FLOAT:
			return true;
		default:
			return false;
		}
	}

	int Parser::getOpLevel(int tokenType){
		switch(tokenType){
		case TOKEN_EQUALS:
			return -1;
		case TOKEN_PLUS:
			return 0;
		case TOKEN_MINUS:
			return 0;
		case TOKEN_MULT:
			return 1;
		case TOKEN_DIV:
			return 1;
		default:
			throw ParserException("Unexpected tokentype error");
		}

		
	}

	void Parser::gotoNextStatement(){
		Token* k = lexer.getReadAheadToken();
		while( k->tokenType != TOKEN_SEMICOLON && k->tokenType != TOKEN_EOF){
			lexer.getNextToken();
			k = lexer.getReadAheadToken();
		}
		lexer.getNextToken();
	}

	SyntaxTreeList* Parser::generateBlock(Namespace* newNamespace){
		/*
		* A block is defined by any area enclosed by curly braces.
		* With the exception of the global block, which contains no braces.
		* When generateStatement reaches a nodeType of NODE_BLOCK_END, this method is terminated.
		*/
		SyntaxTreeList* ret = new SyntaxTreeList;
		while(true){
			SyntaxTree* newTree = NULL;
			newTree = getNextStatement(newNamespace);

			if( newTree == NULL ) continue;
			else if( newTree->nodeType == NODE_EOF){
				// End of block without braces.
				throw ParserException("TOKEN_RCURLY", "TOKEN_EOF", lexer.fileReader.getCurrentLine());
			}
			else if( newTree->nodeType == NODE_BLOCK_END ){
				// End of the block.
				delete newTree;
				break;
			}
			else {
				// Just a normal statement
				ret->push_back(newTree);
			}
		}

		return ret;
	}

	void Parser::generateSyntaxTree() {
		bool exceptionsOccured = false;
		// Create the system types.
		createSystemTypes();
		while(true){
			SyntaxTree* newTree = NULL;
			try {
				newTree = getNextStatement(&globalNamespace);
			}
			catch(std::exception e){
				cout << e.what() << endl;
				exceptionsOccured = true;
				gotoNextStatement();
			}

			if( newTree != NULL && newTree->nodeType == NODE_EOF){
				break;
			}
			else if( newTree != NULL ){

				// Add it to the list.
				syntaxList.push_back(newTree);
			}
		}

		if( exceptionsOccured){
			throw ParserException("Parsing failed.","");
		}


	}

	vector<SyntaxTree*>& Parser::getSyntaxTree(){
		return syntaxList;
	}

	Namespace& Parser::getGlobalNamespace(){
		return globalNamespace;
	}
}
